package com.sukaiyi.giteeideaplugin.mainwindow;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.intellij.icons.AllIcons;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.components.JBLabel;
import com.sukaiyi.giteeideaplugin.cellrenderer.RepoListCellRenderer;
import com.sukaiyi.giteeideaplugin.component.LoadingContainer;
import com.sukaiyi.giteeideaplugin.utils.BrowseUtils;
import com.sukaiyi.giteeideaplugin.utils.ImageUtils;
import com.sukaiyi.giteeideaplugin.utils.NotificationUtils;
import com.sukaiyi.giteejavaapi.common.Gitee;
import com.sukaiyi.giteejavaapi.common.Params;
import com.sukaiyi.giteejavaapi.http.model.HttpRequest;
import com.sukaiyi.giteejavaapi.http.model.HttpResponse;
import icons.PluginIcons;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author sukaiyi
 * @date 2020/06/30
 */
public class PersonalWindow extends ClickableMouseListenerAdapter implements LoadingContainer.Loadable {

    private static final com.intellij.openapi.diagnostic.Logger logger = Logger.getInstance(PersonalWindow.class);

    private final ToolWindow toolWindow;

    private JPanel content;
    private JBLabel avatarLabel;
    private JBLabel nameLabel;
    private JBLabel loginLabel;
    private JBLabel bioLabel;

    private JBLabel starsCountLabel;
    private JBLabel watchesCountLabel;
    private JBLabel followersCountLabel;
    private JBLabel followingCountLabel;
    private JPanel watchesPanel;
    private JPanel starsPanel;
    private JPanel followersPanel;
    private JPanel followingPanel;
    private JList<JSONObject> repoList;
    private JPanel toolbarPanel;
    private JComboBox<RepoFilterItem> repoFilterComboBox;
    private static final List<RepoFilterItem> filterItems = Arrays.asList(
            new RepoFilterItem("all", "所有", PluginIcons.SHELF),
            new RepoFilterItem("public", "公开", PluginIcons.REPO_BLUE),
            new RepoFilterItem("private", "私有", PluginIcons.LOCK_DARK)
    );

    public PersonalWindow(ToolWindow toolWindow) {
        this.toolWindow = toolWindow;
        starsPanel.addMouseListener(this);
        watchesPanel.addMouseListener(this);
        followersPanel.addMouseListener(this);
        followingPanel.addMouseListener(this);
        repoList.setCellRenderer(new RepoListCellRenderer());
        repoList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (repoList.getSelectedIndex() != -1 && e.getClickCount() == 2) {
                    new RepoDetailWindowDialogWrapper(repoList.getSelectedValue()).show();
                }
            }
        });
        filterItems.forEach(repoFilterComboBox::addItem);
        repoFilterComboBox.setRenderer(new RepoFilterCellRenderer());
        repoFilterComboBox.addItemListener(e -> reloadDataAsync());

        DefaultActionGroup actionGroup = createActionGroup();
        ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("Group Toolbar", actionGroup, true);
        toolbarPanel.add(actionToolbar.getComponent());
        reloadDataAsync();
    }

    private void reloadDataAsync() {
        loading();
        Gitee.getInstance().invoke("getV5User", null)
                .thenApply(HttpResponse::asJSONObject)
                .thenApply(obj -> {
                    Map<String, Object> ret = new HashMap<>(obj);
                    HttpRequest request = new HttpRequest("GET", obj.getStr("avatar_url"), new HashMap<String, String>() {{
                        put("Host", "gitee.com");
                        put("User-Agent", "GiteeIdeaPlugin");
                    }}, null);
                    CompletableFuture<HttpResponse> avatarFuture = Gitee.getInstance().invoke(request);
                    HttpResponse response = avatarFuture.join();
                    Icon avatar = Optional.of(response)
                            .map(HttpResponse::asByteArray)
                            .map(ImageUtils::byte2Image)
                            .map(image -> ImageUtils.scaleTo(image, 64, 64))
                            .map(ImageIcon::new)
                            .orElse(null);
                    ret.put("avatar_icon", avatar);
                    return ret;
                })
                .thenApply(obj -> {
                    String visibility = Optional.of(repoFilterComboBox)
                            .map(JComboBox::getSelectedItem)
                            .map(e -> (RepoFilterItem) e)
                            .map(RepoFilterItem::getKey)
                            .orElse("all");
                    Params params = Params.create()
                            .set("visibility", visibility)
                            .set("affiliation", "owner")
                            .set("sort", "pushed")
                            .set("direction", "desc")
                            .set("page", "1")
                            .set("per_page", "20");
                    CompletableFuture<HttpResponse> repoFuture = Gitee.getInstance().invoke("getV5UserRepos", params);
                    HttpResponse response = repoFuture.join();
                    obj.put("repos", response.asJSONArray());
                    return obj;
                })
                .whenComplete((obj, throwable) -> {
                    loaded();
                    if (throwable != null) {
                        NotificationUtils.notify(throwable.getMessage(), NotificationType.ERROR);
                        return;
                    }
                    SwingUtilities.invokeLater(() -> {
                        avatarLabel.setIcon((Icon) obj.get("avatar_icon"));
                        nameLabel.setText((String) obj.get("name"));
                        loginLabel.setText(String.format("@%s - %s", obj.get("name"), obj.get("html_url")));
                        bioLabel.setText((String) obj.get("bio"));

                        starsCountLabel.setText(String.valueOf(obj.get("stared")));
                        watchesCountLabel.setText(String.valueOf(obj.get("watched")));
                        followersCountLabel.setText(String.valueOf(obj.get("followers")));
                        followingCountLabel.setText(String.valueOf(obj.get("following")));

                        JSONArray repos = ((JSONArray) obj.get("repos"));
                        List<JSONObject> repoObjs = new ArrayList<>(repos.size());
                        for (int i = 0; i < repos.size(); i++) {
                            repoObjs.add(repos.getJSONObject(i));
                        }
                        repoList.setListData(repoObjs.toArray(new JSONObject[0]));
                    });
                });
    }

    private void deleteSelectedRepo() {
        loading();
        JSONObject repo = repoList.getSelectedValue();
        Params params = Params.create()
                .set("owner", repo.getByPath("namespace.path", String.class))
                .set("repo", repo.getStr("path"));
        Gitee.getInstance().invoke("deleteV5ReposOwnerRepo", params).whenComplete((res, ex) -> {
            if (ex != null) {
                loaded();
                NotificationUtils.notify(ex.getMessage(), NotificationType.ERROR);
            }
            reloadDataAsync();
        });
    }

    private DefaultActionGroup createActionGroup() {
        DefaultActionGroup actionGroup = new DefaultActionGroup();
        // 刷新页面
        actionGroup.add(new AnAction(AllIcons.Actions.Refresh) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent event) {
                reloadDataAsync();
            }
        });
        // clone
        actionGroup.add(new AnAction(AllIcons.Actions.TraceInto) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
                JSONObject repo = repoList.getSelectedValue();
                if (repo != null) {
                    new CloneRepoWindow(repo).show();
                }
            }
        });
        // 删除仓库
        actionGroup.add(new AnAction(AllIcons.General.Remove) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
                JSONObject repo = repoList.getSelectedValue();
                if (repo != null && new DeleteRepoConfirmWindow(repo).showAndGet()) {
                    deleteSelectedRepo();
                }
            }
        });
        // 浏览器中打开
        actionGroup.add(new AnAction(AllIcons.General.Web) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
                JSONObject repo = repoList.getSelectedValue();
                if (repo != null) {
                    BrowseUtils.open(repo.getStr("html_url"));
                }
            }
        });
        actionGroup.addSeparator();
//        actionGroup.add(new AnAction(PluginIcons.SHELF) {
//            @Override
//            public void actionPerformed(@NotNull AnActionEvent e) {
//                new DialogWrapper(true) {
//                    {
//                        init();
//                    }
//
//                    @Override
//                    protected @Nullable JComponent createCenterPanel() {
//                        JBCefBrowser myBrowser = new JBCefBrowser("https://www.baidu.com");
//                        return myBrowser.getComponent();
//                    }
//                }.show();
//            }
//        });
        actionGroup.add(new AnAction(AllIcons.Actions.Help) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
            }
        });
        return actionGroup;
    }

    @Override
    public JPanel getContent() {
        return content;
    }

    @Override
    public void mouseClicked(MouseEvent mouseEvent) {
        logger.info("source:{}" + mouseEvent.getSource());
    }

    public void createUIComponents() {
    }

    private static final class RepoFilterCellRenderer extends ColoredListCellRenderer<RepoFilterItem> {
        @Override
        protected void customizeCellRenderer(@NotNull JList<? extends RepoFilterItem> list, RepoFilterItem value, int index, boolean selected, boolean hasFocus) {
            setIcon(value.getIcon());
            append(" ");
            append(value.getName());
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private static final class RepoFilterItem {
        private String key;
        private String name;
        private Icon icon;
    }
}
